//
//  ZSerialIO.h
//  Part of Z-Way.C library
//
//  Created by Alex Skalozub on 1/9/12.
//  Based on Z-Way source code written by Christian Paetz and Poltorak Serguei
//
//  Copyright (c) 2012 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zway_serial_io_h
#define zway_serial_io_h

#include "ZPlatform.h"
#include "ZLog.h"

enum _ZW_HANDLE_TYPE
{
    ZW_HANDLE_TYPE_INVALID = 0,
    ZW_HANDLE_TYPE_TTY,
    ZW_HANDLE_TYPE_UNIX,
    ZW_HANDLE_TYPE_BLE,
    ZW_HANDLE_TYPE_TCP,
    ZW_HANDLE_TYPE_UDP
};
typedef enum _ZW_HANDLE_TYPE ZW_HANDLE_TYPE;

// Available UART speeds
#define UART_SPEEDS  {  1200,  2400,  1800,  4800,  9600, 19200,   38400,  57600,  115200,  230400,  460800,  921600 }
#define UART_BSPEEDS { B1200, B2400, B1800, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600 }

struct _ZWHANDLE
{
    ZW_FILE_HANDLE fd;
#if !defined(__ESP32__)
    ZW_HANDLE_TYPE type;
    void *data; // for protocol custom data - memory should be handled by the protocol manager
    size_t data_len;
#endif
};
typedef struct _ZWHANDLE *ZWHANDLE;

ZWEXPORT_PRIVATE ZWBOOL zio_open(ZWLog logger, const ZIoPortSettings_t settings, ZWHANDLE *handle);

ZWEXPORT_PRIVATE void zio_close(ZWLog logger, ZWHANDLE *handle);

static inline ZW_HANDLE_TYPE zio_type(ZWHANDLE handle)
{
    if (handle == NULL)
    {
        return ZW_HANDLE_TYPE_INVALID;
    }
#if defined(__ESP32__)
    return ZW_HANDLE_TYPE_TTY;
#else
    return handle->type;
#endif
};

ZWEXPORT_PRIVATE void zio_configure(ZWLog logger, ZWHANDLE handle, speed_t baudRate);

ZWEXPORT_PRIVATE int zio_write(ZWLog logger, ZWHANDLE handle, const ZWBYTE *buffer, size_t size);

ZWEXPORT_PRIVATE int zio_read(ZWLog logger, ZWHANDLE handle, ZWBYTE *buffer, size_t size);

ZWEXPORT_PRIVATE ZWBOOL zio_check_speed(ZWLog log, speed_t speed);

static inline
#if !defined(__ESP32__)
    const
#endif
    ZIoPortSettings_t
    zio_port_settings_generate(ZWCSTR name, ZWBYTE uart_num, ZWBYTE tx_pin, ZWBYTE rx_pin, ZWWORD rx_buffer_size)
{
#if defined(__ESP32__)
    ZIoPortSettings_t settings;
    settings.rx_buffer_size = rx_buffer_size;
    settings.uart_num = uart_num;
    settings.tx_pin = tx_pin;
    settings.rx_pin = rx_pin;
    return settings;
    (void)name;
#else
    return name;
    (void)uart_num;
    (void)tx_pin;
    (void)rx_pin;
    (void)rx_buffer_size;
#endif
};

static inline ZWBOOL _zio_should_increase_channel_timeout(ZW_HANDLE_TYPE const type)
{
#if defined(Z_PLATFORM_LOW_PERFORMANCE)
    return FALSE;
    (void)type;
#else
    switch (type)
    {
        case ZW_HANDLE_TYPE_UDP:
        case ZW_HANDLE_TYPE_TCP:
        case ZW_HANDLE_TYPE_UNIX:
            return TRUE;
        case ZW_HANDLE_TYPE_INVALID:
        case ZW_HANDLE_TYPE_TTY:
        case ZW_HANDLE_TYPE_BLE:
            return FALSE;
    }
    return FALSE;
#endif
};

static inline ZWBOOL _zio_should_configure(ZW_HANDLE_TYPE const type)
{
#if defined(__ESP32__)
    return TRUE;
    (void)type;
#else
    if (type == ZW_HANDLE_TYPE_TTY)
    {
        return TRUE;
    }
    return FALSE;
#endif
};

static inline ZWBOOL _zio_is_slow_io(const ZWHANDLE handle)
{
#if defined(Z_PLATFORM_LOW_PERFORMANCE)
    return TRUE; // is too slow when handling HTTP requests, increase Serial API timeouts
#else
    switch (zio_type(handle))
    {
        case ZW_HANDLE_TYPE_UDP:
        case ZW_HANDLE_TYPE_TCP:
        case ZW_HANDLE_TYPE_UNIX:
        case ZW_HANDLE_TYPE_BLE:
            return TRUE; // running on socket, increase Serial API timeouts
        case ZW_HANDLE_TYPE_INVALID:
        case ZW_HANDLE_TYPE_TTY:
            break;
    }
    return FALSE;
#endif
}

#endif
